package cn.hamster3.hamsterworld.core;

import cn.hamster3.api.HamsterAPI;
import cn.hamster3.hamsterworld.HamsterWorld;
import cn.hamster3.hamsterworld.data.WorldData;
import cn.hamster3.hamsterworld.event.PrivateWorldDeleteEvent;
import cn.hamster3.hamsterworld.event.PrivateWorldPostCreateEvent;
import cn.hamster3.hamsterworld.event.PrivateWorldPreCreateEvent;
import org.bukkit.Bukkit;
import org.bukkit.Difficulty;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

public class DataManager {
    private SimpleDateFormat dateFormat;
    private HamsterWorld plugin;
    private File worldDataFolder;

    private int worldBorderSize;
    private double createWorldCost;
    private double rebuildWorldCost;
    private String privateWorldName;
    private List<String> whiteListWorlds;

    private HashSet<WorldData> worldData;

    public DataManager(HamsterWorld plugin) {
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 初始化存档管理器...");
        this.plugin = plugin;
        worldDataFolder = new File(plugin.getDataFolder(), "WorldData");
        dateFormat = new SimpleDateFormat("_yyyy-MM-dd HH-mm-ss");

        if (worldDataFolder.mkdirs()) {
            HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 创建世界存档文件夹...");
        }

        reload();
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 存档管理器初始化完成!");
    }

    public void reload() {
        if (worldData != null) {
            saveAllData();
        }
        plugin.saveDefaultConfig();
        plugin.reloadConfig();
        FileConfiguration config = plugin.getConfig();

        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 加载消息设置...");
        ConfigurationSection messagesConfig = config.getConfigurationSection("messages");
        for (String s : messagesConfig.getKeys(false)) {
            try {
                Message.valueOf(s).setMessage(HamsterAPI.replaceColorCode(messagesConfig.getString(s)));
            } catch (IllegalArgumentException e) {
                HamsterAPI.sendConsoleMessage("§c[HamsterWorld] 没有字段 %s 的消息!", s);
                e.printStackTrace();
            }
        }
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 消息设置加载完成!");
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 加载 config 文件...");
        worldBorderSize = config.getInt("worldBorder", 5000);
        createWorldCost = config.getDouble("createWorldCost");
        rebuildWorldCost = config.getDouble("rebuildWorldCost");
        privateWorldName = config.getString("privateWorldName");
        whiteListWorlds = config.getStringList("whiteListWorlds");
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] config 加载完成!");

        worldData = new HashSet<>();
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 加载世界存档...");
        File[] files = worldDataFolder.listFiles();
        if (files != null) {
            for (File file : files) {
                try {
                    worldData.add(new WorldData(YamlConfiguration.loadConfiguration(file)));
                } catch (Exception e) {
                    HamsterAPI.sendConsoleMessage("§c[HamsterWorld] 加载世界存档 %s 时出错!", file.getName());
                    e.printStackTrace();
                }
            }
        }
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 世界存档加载完成!");
    }

    public void saveAllData() {
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 保存世界存档...");
        for (WorldData data : worldData) {
            data.save(worldDataFolder);
        }
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 世界存档保存完成!");
    }

    public World createWorld(Player player) {
        String worldName = privateWorldName.replace("%player%", player.getName());
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 准备创建世界, 名称: %s.", worldName);
        if (getWorldData(player) != null) {
            HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 玩家 %s 已经拥有世界, 停止创建工作.", player.getName());
            return null;
        }

        WorldCreator worldCreator = new WorldCreator(worldName);
        // 生成结构
        worldCreator.generateStructures(true);

        PrivateWorldPreCreateEvent preCreateEvent = new PrivateWorldPreCreateEvent(worldCreator, player.getUniqueId());
        Bukkit.getPluginManager().callEvent(preCreateEvent);
        if (preCreateEvent.isCancelled()) {
            return null;
        }

        World world = worldCreator.createWorld();

        // 关闭死亡掉落
        world.setGameRuleValue("keepInventory", "true");
        world.setTime(Bukkit.getWorlds().get(0).getTime());

        WorldData data = new WorldData(
                player.getUniqueId(),
                world.getUID(),
                worldName,
                world.getSeed()
        );
        worldData.add(data);
        data.setBorderSize(worldBorderSize);
        PrivateWorldPostCreateEvent postCreateEvent = new PrivateWorldPostCreateEvent(worldCreator, data);
        Bukkit.getPluginManager().callEvent(postCreateEvent);
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 世界 %s 创建完成.", data.getName());
        return world;
    }

    public void deleteWorld(WorldData data) {
        if (data == null) {
            return;
        }
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 准备删除世界 %s ...", data.getName());
        worldData.remove(data);
        if (new File(worldDataFolder, data.getName() + ".yml").delete()) {
            HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 删除了世界设定文件: %s", data.getName());
        }

        World world = data.getWorld();
        if (world != null) {
            for (Player worldPlayer : world.getPlayers()) {
                worldPlayer.sendMessage(Message.worldRebuildKick.toString());
                worldPlayer.teleport(Bukkit.getWorlds().get(0).getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
            }
            Bukkit.unloadWorld(world, true);
            renameFile(world.getWorldFolder());
        }
        PrivateWorldDeleteEvent deleteEvent = new PrivateWorldDeleteEvent(data);
        Bukkit.getPluginManager().callEvent(deleteEvent);
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 世界 %s 删除完成.(但是存档文件还没删", data.getName());
    }

    public void loadWorld(WorldData worldData) {
        if (worldData == null) {
            return;
        }
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 加载世界 %s ...", worldData.getName());
        WorldCreator worldCreator = new WorldCreator(worldData.getName());
        worldCreator.generateStructures(true);
        World world = worldCreator.seed(worldData.getSeed()).createWorld();

        // 关闭死亡掉落
        world.setGameRuleValue("keepInventory", "true");
        // 困难难度
        world.setDifficulty(Difficulty.HARD);

        if (worldData.isRealTime()) {
            // 关闭时间推移
            world.setGameRuleValue("doDaylightCycle", "false");
        } else {
            // 开启时间推移
            world.setGameRuleValue("doDaylightCycle", "true");
        }

        world.setTime(Bukkit.getWorlds().get(0).getTime());
        worldData.setBorderSize(worldData.getBorderSize());
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 世界 %s 加载完成!", worldData.getName());
    }

    public void rebuildWorld(Player player) {
        player.sendMessage(Message.worldRebuilding.toString());

        WorldData data = getWorldData(player);
        if (data == null) {
            return;
        }
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 准备重建世界 %s ...", data.getName());
        deleteWorld(data);

        World world = createWorld(player);
        if (world == null) {
            player.sendMessage(Message.worldRebuildFailed.toString());
            return;
        }
        player.sendMessage(Message.worldRebuildDone.toString());
        player.teleport(world.getSpawnLocation());
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 世界 %s 重建完成.", getWorldData(player).getName());
    }

    public List<String> getWhiteListWorlds() {
        return whiteListWorlds;
    }

    public HashSet<WorldData> getWorldData() {
        return worldData;
    }

    public WorldData getWorldData(String name) {
        for (WorldData data : worldData) {
            if (data.getName().equals(name)) {
                return data;
            }
        }
        return null;
    }

    public WorldData getWorldData(World world) {
        for (WorldData data : worldData) {
            if (data.getUuid().equals(world.getUID())) {
                return data;
            }
        }
        return null;
    }

    public WorldData getWorldData(Player player) {
        for (WorldData data : worldData) {
            if (data.getOwner().equals(player.getUniqueId())) {
                return data;
            }
        }
        return null;
    }

    public boolean isWhiteList(String name) {
        return whiteListWorlds.contains(name);
    }

    public double getCreateWorldCost() {
        return createWorldCost;
    }

    public double getRebuildWorldCost() {
        return rebuildWorldCost;
    }

    private void renameFile(File file) {
        HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 重命名文件: %s", file.getAbsoluteFile());
        String name = file.getAbsolutePath() + dateFormat.format(new Date());
        if (file.renameTo(new File(name))) {
            HamsterAPI.sendConsoleMessage("§a[HamsterWorld] 文件已重命名为: %s", name);
        } else {
            HamsterAPI.sendConsoleMessage("§c[HamsterWorld] 文件重命名失败!");
        }
    }
}
